package com.google.code.p.fop_qrcode;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationUtil;
import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.XMLHandler;
import org.apache.fop.render.ps.PSRenderer;
import org.apache.fop.render.ps.PSRendererContextConstants;
import org.w3c.dom.Document;

import com.d_project.qrcode.ErrorCorrectLevel;
import com.d_project.qrcode.QRCode;

public class QRCodeXMLHandler implements XMLHandler, PSRendererContextConstants {
    public static final float DEFAULT_LENGTH = 16.0f;
    public static final int DEFAULT_TYPE = 1;
    public static final int DEFAULT_CELL_SIZE = 5;
    public static final int DEFAULT_MARGIN_SIZE = 25;
    public static final String DEFAULT_ERROR_CORRECTION_TYPE = "L";
  
    public void handleXML(RendererContext context, Document doc, String ns) throws Exception {
        int dpi = (int) context.getUserAgent().getSourceResolution();
        
        Configuration cfg = ConfigurationUtil.toConfiguration(doc.getDocumentElement());        
        String msg = cfg.getAttribute("message");
        int typeNumber = cfg.getAttributeAsInteger("type", DEFAULT_TYPE);
        int correction = getErrorCorrectionLevel(cfg.getAttribute("correction", DEFAULT_ERROR_CORRECTION_TYPE));
        int cellsize = cfg.getAttributeAsInteger("cellsize", DEFAULT_CELL_SIZE);
        int margin = cfg.getAttributeAsInteger("margin", DEFAULT_MARGIN_SIZE);
        float length = cfg.getAttributeAsFloat("length", DEFAULT_LENGTH);
        
        QRCode qrcode = new QRCode();
        qrcode.setTypeNumber(typeNumber);
        qrcode.setErrorCorrectLevel(correction);
        qrcode.addData(msg);
        qrcode.make();

        QRCode2SVG conv = new QRCode2SVG();
        Document svg = conv.getSvgDocumentFromQRCode(qrcode, dpi, length, cellsize, margin);
        context.getRenderer().renderXML(context, svg, SVGDOMImplementation.SVG_NAMESPACE_URI);
    }

    public boolean supportsRenderer(Renderer renderer) {
        return (renderer instanceof PSRenderer) || (renderer.getGraphics2DAdapter() != null);
    }

    public String getNamespace() {
        return QRCodeElementMapping.NAMESPACE;
    }
    
    public String getMimeType() {
        return XMLHandler.HANDLE_ALL;
    }

    private int getErrorCorrectionLevel(String level){
        level = level.toLowerCase();        
        if ("h".equals(level)) {
            return ErrorCorrectLevel.H;
        } else if ("l".equals(level)) {
            return ErrorCorrectLevel.L;
        } else if ("m".equals(level)) {
            return ErrorCorrectLevel.M;
        } else if ("q".equals(level)) {
            return ErrorCorrectLevel.Q;
        } else {
            throw new IllegalArgumentException("qrcode error correction level must be either one of: H/L/M/Q");
        }
    }

}
